import fabricItemAlign from "@/utils/align";
import FontFaceObserver from "fontfaceobserver";

const app = {
  state: {
    //画布
    canvas: null,
    //选择的对象 意义不大
    selectedObj: null,
    //画布状态，目前好像没有用
    canvasState: null,
    _clipboard: null,
    //撤销列表
    undoList: [],
    //反撤销列表
    redoList: [],
    //预览的图片
    previewImg: null,

    //默认为折叠状态
    leftState: false,
    rightState: false,

    //选择对象的类型
    type: ""
  },
  mutations: {
    //初始化画布
    INIT_CANVAS: (state, fCanvas) => {
      state.canvas = fCanvas;
    },

    SET_LEFTSTATE: (state, v) => {
      state.leftState = v;
    },
    SET_RIGHTSTATE: (state, v) => {
      state.rightState = v;
    },

    //设置选择的对象
    SET_SELECTEDOBJ: (state, object) => {
      state.selectedObj = object;
      state.type = object ? object.type : "";
    },

    //设置状态
    SET_CANVASSTATE: (state, canvasState) => {
      state.canvasState = canvasState;
    },

    //加入到撤销队列的后面
    ADD_UNDO: (state, canvasState) => {
      state.undoList.push(canvasState);
    },

    //弹出最后加入的撤销队列
    POP_UNDO: state => {
      state.undoList.pop();
    },

    //加入到反撤销队列
    ADD_REDO: (state, canvasState) => {
      state.redoList.push(canvasState);
    },

    //弹出反撤销最后加入的数据
    POP_REDO: state => {
      state.redoList.pop();
    },

    //重新设置反撤销队列
    SET_REDOLIST: (state, list) => {
      state.redoList = list;
    },

    //预览图片
    SET_PREVIEW_IMG: (state, img) => {
      state.previewImg = img;
    }
  },
  //同步方法
  actions: {
    initCanvas({ commit }, fCanvas) {
      commit("INIT_CANVAS", fCanvas);
    },

    setLeftState({ commit }, v) {
      commit("SET_LEFTSTATE", v);
    },
    setRightState({ commit }, v) {
      commit("SET_RIGHTSTATE", v);
    },

    //读取操作
    align({ commit, state, dispatch }, alignParam) {
      if (state.canvas.getActiveObjects().length > 1) {
        //排序
        fabricItemAlign(state.canvas, alignParam);

        dispatch("saveState");
      }
    },
    //改变字体
    font({ commit, state, dispatch }, fname) {
      if (!state.canvas.getActiveObject()) return;
      console.log(state.canvas.getActiveObject());

      console.time("字体加载用时");
      var ooo = new FontFaceObserver(fname);
      ooo.load(null, 60000).then(() => {
        //设置字体
        let arr = state.canvas.getActiveObject()._objects || [
          state.canvas.getActiveObject()
        ];
        arr.map(item => {
          item.set("fontFamily", fname);
        });
        state.canvas.requestRenderAll();

        //记录历史
        dispatch("saveState");

        console.timeEnd("字体加载用时");
      });
    },
    addWord({ commit, state, dispatch }, px) {
      console.log(state.canvas.width);
      //得到屏幕的中心
      const textbox = new fabric.Textbox("双击修改文字", {
        left:
          state.canvas.width / 2 / state.canvas.getZoom() -
          //减去内部偏移
          state.canvas.viewportTransform[4] / state.canvas.getZoom(),
        top:
          state.canvas.height / 2 / state.canvas.getZoom() -
          state.canvas.viewportTransform[5] / state.canvas.getZoom(),
        fontSize: px,
        hasControls: true,
        hasBorders: true,
        originX: "center",
        fontWeight: 400,
        charSpacing: 3,
        opacity: 1,
        lineHeight: 1.3,
        originY: "center"
        //borderColor: "#ff8d23",
        //editingBorderColor: "#ff8d23"
      });

      state.canvas.add(textbox).setActiveObject(textbox);
      dispatch("zhiding");

      //commit("SET_SELECTEDOBJ", textbox);
    },
    addBackground({ commit, state, dispatch }, url) {
      //双击的时候效果....
      //   state.canvas.getObjects("_lxw_mask")[0].set("opacity", "0");
      //   //加载背景图片
      let bg = state.canvas.getObjects("_lxw_bg")[0];

      //   state.canvas.centeredScaling = false;

      fabric.util.loadImage(
        url,
        img => {
          //加载背景图片
          let bgimg = new fabric.Image(img);

          let blx = bgimg.width / bg.width;
          let bly = bgimg.height / bg.height;

          //按照小的来，大的就应该超过
          if (blx > bly) blx = bly;
          let leftx = (bgimg.width / blx - bg.width) / 2;
          let topy = (bgimg.height / blx - bg.height) / 2;

          let clipBOX = new fabric.Rect({
            left: bg.left,
            top: bg.top,
            absolutePositioned: true,
            width: bg.width,
            height: bg.height,
            selectable: false
          });

          bgimg.set({
            left: bg.left - leftx,
            top: bg.top - topy,
            opacity: 1,

            scaleX: 1 / blx,
            scaleY: 1 / blx,

            //为什么是中间??真奇葩
            clipPath: clipBOX,
            selectable: false,
            transparentCorners: false,

            excludeFromExport: true,
            hasControls: false,
            perPixelTargetFind: false,
            lxwname: "_lxw_",
            type: "_lxw_bgimg"
          });

          //双击事件,点击确定的时候 需要再还原信息
          bgimg.on("mousedblclick", () => {
            state.canvas.getObjects("_lxw_mask")[0].set("opacity", "0");
            state.canvas.centeredScaling = false;

            let clipBOXClone = new fabric.Image(img);

            clipBOXClone.set({
              left: bg.left - leftx,
              top: bg.top - topy,
              opacity: 0.3,
              scaleX: 1 / blx,
              scaleY: 1 / blx
            });
            state.canvas.add(clipBOXClone);

            clipBOXClone.on({
              //拖动的时候，双击才显示出来
              moving: e => {
                //不能脱出空白的内容
                if (clipBOXClone.left > bg.left) clipBOXClone.left = bg.left;
                else if (
                  clipBOXClone.left + clipBOXClone.width * clipBOXClone.scaleX <
                  bg.left + bg.width
                )
                  clipBOXClone.left =
                    bg.left +
                    bg.width -
                    clipBOXClone.width * clipBOXClone.scaleX;

                if (clipBOXClone.top > bg.top) clipBOXClone.top = bg.top;
                else if (
                  clipBOXClone.top + clipBOXClone.height * clipBOXClone.scaleY <
                  bg.top + bg.height
                ) {
                  clipBOXClone.top =
                    bg.top +
                    bg.height -
                    clipBOXClone.height * clipBOXClone.scaleY;
                }

                bgimg.left = clipBOXClone.left;
                bgimg.top = clipBOXClone.top;

                bgimg.width = clipBOXClone.width;
                bgimg.height = clipBOXClone.height;

                bgimg.set("dirty", true);
                state.canvas.renderAll();
              },
              scaling: () => {
                if (
                  clipBOXClone.width * clipBOXClone.scaleX <
                  bgimg.width / blx
                )
                  clipBOXClone.scaleX = bgimg.width / blx / clipBOXClone.width;
                if (
                  clipBOXClone.height * clipBOXClone.scaleY <
                  bgimg.height / blx
                )
                  clipBOXClone.scaleY =
                    bgimg.height / blx / clipBOXClone.height;

                bgimg.scaleX = clipBOXClone.scaleX;
                bgimg.scaleY = clipBOXClone.scaleY;

                bgimg.left = clipBOXClone.left;
                bgimg.top = clipBOXClone.top;

                bgimg.width = clipBOXClone.width;
                bgimg.height = clipBOXClone.height;

                state.canvas.renderAll();
              }
            });
          });

          state.canvas.add(bgimg);

          //   clipBOXClone.on({
          //     //拖动的时候，双击才显示出来
          //     moving: e => {
          //       bgimg.left = clipBOXClone.left;
          //       bgimg.top = clipBOXClone.top;

          //       bgimg.width = clipBOXClone.width;
          //       bgimg.height = clipBOXClone.height;

          //       bgimg.set("dirty", true);
          //       state.canvas.renderAll();
          //     },
          //     scaling: () => {
          //       //矩形会变小？
          //       bgimg.scaleX = clipBOXClone.scaleX;
          //       bgimg.scaleY = clipBOXClone.scaleY;

          //       bgimg.left = clipBOXClone.left;
          //       bgimg.top = clipBOXClone.top;

          //       bgimg.width = clipBOXClone.width;
          //       bgimg.height = clipBOXClone.height;

          //       state.canvas.renderAll();
          //     }
          //   });

          //bg.set("fill", pattern);
          //bg.bringToFront();
          state.canvas.renderAll();
        },
        { crossOrigin: "anonymous" }
      );
    },
    //备份一下
    addBackground4({ commit, state, dispatch }, url) {
      //双击的时候效果....
      state.canvas.getObjects("_lxw_mask")[0].set("opacity", "0");
      //加载背景图片
      let bg = state.canvas.getObjects("_lxw_bg")[0];

      state.canvas.centeredScaling = false;

      let clipBOX = new fabric.Rect({
        left: bg.left,
        top: bg.top,
        absolutePositioned: true,
        width: 300,
        height: 300,

        selectable: false
      });

      fabric.util.loadImage(
        url,
        img => {
          //加载背景图片
          let bgimg = new fabric.Image(img);
          bgimg.set({
            left: bg.left,
            top: bg.top,
            //调整为跟蒙版一样大
            // width: 300,
            // height: 300,
            opacity: 1,

            //为什么是中间??真奇葩
            clipPath: clipBOX,
            selectable: false,
            hasControls: false,
            evented: false
          });

          let clipBOXClone = new fabric.Image(img);

          clipBOXClone.set({
            left: bg.left,
            top: bg.top,
            opacity: 0.3
          });
          state.canvas.add(clipBOXClone);
          state.canvas.add(bgimg);

          clipBOXClone.on({
            //拖动的时候，双击才显示出来
            moving: e => {
              bgimg.width -= e.e.movementX / state.canvas.getZoom();
              bgimg.height -= e.e.movementY / state.canvas.getZoom();

              bgimg.left += e.e.movementX / state.canvas.getZoom();
              bgimg.top += e.e.movementY / state.canvas.getZoom();

              bgimg.set("dirty", true);
              state.canvas.renderAll();
            },
            scaling: () => {
              //矩形会变小？
              bgimg.scaleX = clipBOXClone.scaleX;
              bgimg.scaleY = clipBOXClone.scaleY;

              bgimg.left = clipBOXClone.left;
              bgimg.top = clipBOXClone.top;

              bgimg.width = clipBOXClone.width;
              bgimg.height = clipBOXClone.height;

              state.canvas.renderAll();
            }
          });

          //bg.set("fill", pattern);
          //bg.bringToFront();
          state.canvas.renderAll();
        },
        { crossOrigin: "anonymous" }
      );
    },
    //通过clippath拖动
    addBackground3({ commit, state, dispatch }, url) {
      state.canvas.getObjects("_lxw_mask")[0].set("opacity", "0");
      //加载背景图片
      let bg = state.canvas.getObjects("_lxw_bg")[0];
      //bg.set('fill',)

      let clipBOX = new fabric.Rect({
        left: bg.left,
        top: bg.top,
        absolutePositioned: true,
        width: 300,
        height: 300,

        selectable: false
      });

      fabric.util.loadImage(
        url,
        img => {
          //加载背景图片
          let bgimg = new fabric.Image(img);
          bgimg.set({
            left: bg.left,
            top: bg.top,
            width: 300,
            height: 300,
            opacity: 1,
            //为什么是中间??真奇葩
            clipPath: clipBOX,
            selectable: false,
            hasControls: false
          });

          let clipBOXClone = new fabric.Image(img);

          clipBOXClone.set({
            left: bg.left,
            top: bg.top,
            opacity: 0.3
          });
          state.canvas.add(clipBOXClone);
          state.canvas.add(bgimg);

          clipBOXClone.on({
            //拖动的时候，双击才显示出来
            moving: e => {
              //if (bgimg.__down) {
              //clipBOX.left -= e.e.movementX / state.canvas.getZoom();
              //clipBOX.top -= e.e.movementY / state.canvas.getZoom();

              bgimg.width -= e.e.movementX / state.canvas.getZoom();
              bgimg.height -= e.e.movementY / state.canvas.getZoom();

              bgimg.left += e.e.movementX / state.canvas.getZoom();
              bgimg.top += e.e.movementY / state.canvas.getZoom();

              bgimg.set("dirty", true);
              state.canvas.renderAll();
              return;
              //}
            },
            scaling: () => {}
          });

          //bg.set("fill", pattern);
          //bg.bringToFront();
          state.canvas.renderAll();
        },
        { crossOrigin: "anonymous" }
      );
    },
    //通过patten 方式拖动
    addBackground2({ commit, state, dispatch }, url) {
      state.canvas.getObjects("_lxw_mask")[0].set("opacity", "0");
      //加载背景图片
      let bg = state.canvas.getObjects("_lxw_bg")[0];
      //bg.set('fill',)

      fabric.util.loadImage(
        url,
        img => {
          var canvas2 = document.createElement("canvas");
          canvas2.width = bg.width * 1.5;
          canvas2.height = bg.height * 1.5;

          // 坐标(0,0) 表示从此处开始绘制，相当于偏移。
          canvas2
            .getContext("2d")
            .drawImage(img, 0, 0, bg.width * 1.5, bg.height * 1.5);
          console.log("AAAAAAAAAA");
          var image = new Image();

          //跨域问题？必须跟站点通一个域...
          image.setAttribute("crossOrigin", "Anonymous");
          image.src = canvas2.toDataURL("image/jpeg");
          let pattern = new fabric.Pattern({
            source: image,
            //offsetX: 100,
            repeat: "no-repeat"
          });
          //加载完毕
          image.onload = function() {
            let bgimg = new fabric.Image(image);
            bgimg.set({
              left: bg.left,
              top: bg.top,
              opacity: 0.2
            });
            state.canvas.add(bgimg);

            bgimg.on({
              //拖动的时候，双击才显示出来
              moving: e => {
                //if (bgimg.__down) {
                pattern.offsetX += e.e.movementX / state.canvas.getZoom();
                pattern.offsetY += e.e.movementY / state.canvas.getZoom();
                console.log(e.e.movementX, e.e.movementY);
                state.canvas.renderAll();
                return;
                //}
              },
              scaling: () => {}
            });

            bg.set("fill", pattern);
            bg.bringToFront();
            state.canvas.renderAll();
          };
          console.log(image);
        },
        { crossOrigin: "anonymous" }
      );
    },
    //显示图片
    addImage({ commit, state, dispatch }, url) {
      console.log(state.canvas.width);

      fabric.Image.fromURL(
        url,
        img => {
          img.set({
            angle: 0,
            left:
              state.canvas.width / 2 / state.canvas.getZoom() -
              //减去内部偏移
              state.canvas.viewportTransform[4] / state.canvas.getZoom(),
            top:
              state.canvas.height / 2 / state.canvas.getZoom() -
              state.canvas.viewportTransform[5] / state.canvas.getZoom(),
            hasControls: true,
            hasBorders: true,
            opacity: 1,
            originX: "center",
            originY: "center",
            borderColor: "#ff8d23"
          });

          //   // 将 filters 实例 push 进 filters 里头
          //   img.filters.push(new fabric.Image.filters.Grayscale());
          //   // 这边需要重整所有的滤镜效果
          //   img.applyFilters();

          state.canvas.add(img).setActiveObject(img);

          dispatch("saveState");
          dispatch("zhiding");

          //commit("SET_SELECTEDOBJ", img);
        },
        { crossOrigin: "anonymous" }
      );
    },
    zhiding({ commit, state, dispatch }) {
      //设置为指定
      state.canvas.bringToFront(state.canvas.getObjects("_lxw_mask")[0]);
      state.canvas.sendToBack(state.canvas.getObjects("_lxw_bg")[0]);
    },
    copy({ commit, state, dispatch }) {
      state.canvas.getActiveObject().clone(cloned => {
        state._clipboard = cloned;
      });
    },
    paste({ commit, state, dispatch }) {
      // clone again, so you can do multiple copies.
      if (state._clipboard == null) return;

      state._clipboard.clone(clonedObj => {
        state.canvas.discardActiveObject();
        clonedObj.set({
          left: clonedObj.left + 10,
          top: clonedObj.top + 10,
          evented: true
        });
        if (clonedObj.type === "activeSelection") {
          // active selection needs a reference to the canvas.
          clonedObj.canvas = state.canvas;
          clonedObj.forEachObject(obj => {
            state.canvas.add(obj);
          });
          // this should solve the unselectability
          clonedObj.setCoords();
        } else {
          state.canvas.add(clonedObj);
        }
        state._clipboard.top += 10;
        state._clipboard.left += 10;
        state.canvas.setActiveObject(clonedObj);
        state.canvas.requestRenderAll();
      });

      dispatch("saveState");
      dispatch("zhiding");
    },
    //删除
    del({ commit, state, dispatch }, obj = null) {
      if (obj == null) {
        obj = state.canvas.getActiveObject();
      }
      if (obj) {
        console.log(obj, "delete");
        if (obj.type == "group") {
          state.canvas.remove(obj);
        } else {
          let arr = obj._objects || [obj];
          arr.map(o => {
            state.canvas.remove(o);
          });
        }

        //不要选择上对象
        state.canvas.discardActiveObject();
        state.canvas.requestRenderAll();
      }
      dispatch("saveState");
    },
    unselect({ commit, state, dispatch }) {
      state.canvas.discardActiveObject();
      state.canvas.requestRenderAll();

      dispatch("saveState");
    },
    //选择...
    select({ commit, state, dispatch }) {
      state.canvas.discardActiveObject();
      let arr = state.canvas._objects.filter(o => !o.lxwname);
      if (arr.length == 0) return;

      var sel = new fabric.ActiveSelection(arr, {
        canvas: state.canvas
      });
      state.canvas.setActiveObject(sel);
      state.canvas.requestRenderAll();
    },
    group({ commit, state, dispatch }) {
      if (!state.canvas.getActiveObject()) {
        return;
      }
      if (state.canvas.getActiveObject().type !== "activeSelection") {
        return;
      }
      state.canvas.getActiveObject().toGroup();
      state.canvas.requestRenderAll();
      dispatch("saveState");
    },
    ungroup({ commit, state, dispatch }) {
      if (!state.canvas.getActiveObject()) {
        return;
      }
      if (state.canvas.getActiveObject().type !== "group") {
        return;
      }
      state.canvas.getActiveObject().toActiveSelection();
      state.canvas.requestRenderAll();
      dispatch("saveState");
    },

    setSelectedObj({ commit }, object) {
      commit("SET_SELECTEDOBJ", object);
    },

    setCanvasState({ commit }, canvasState) {
      commit("SET_CANVASSTATE", canvasState);
    },

    addUndo({ commit }, canvasState) {
      commit("ADD_UNDO", canvasState);
    },

    popUndo({ commit }) {
      commit("POP_UNDO");
    },

    addRedo({ commit }, canvasState) {
      commit("ADD_REDO", canvasState);
    },

    popRedo({ commit }) {
      commit("POP_REDO");
    },

    setRedo({ commit }, list) {
      commit("SET_REDOLIST", list);
    },

    saveState({ commit, state }) {
      // 清空恢复栈redoList
      commit("SET_REDOLIST", []);

      //把上一个加入到撤销队列
      if (state.canvasState) {
        commit("ADD_UNDO", state.canvasState);
      }

      //记录数据？
      //   console.log(
      //     "AAAAAAA",
      //     state.canvas.toJSON(),
      //     state.canvas.toJSON([
      //       "hasControls",
      //       "borderColor",
      //       "scaleX",
      //       "scaleY",
      //       "angle",
      //       "top",
      //       "left",
      //       "crossOrigin",
      //       "_lxw_name",
      //       "type"
      //     ])
      //   );

      //把当前界面数据缓存起来
      commit(
        "SET_CANVASSTATE",
        state.canvas.toJSON([
          "hasControls",
          "borderColor",
          "scaleX",
          "scaleY",
          "angle",
          "top",
          "left",
          "crossOrigin"
        ])
      );

      // console.log(state.canvasState)
    },
    // 撤销
    undo({ commit, dispatch, state }) {
      //把当前加入到反撤销里面
      commit("ADD_REDO", state.canvasState);
      //复制最后一个的数据状态
      const lastState = { ...state.undoList[state.undoList.length - 1] };

      //设置到当前的状态
      commit("SET_CANVASSTATE", lastState);
      // state.popUndo()

      //删除撤销队列最近的一个
      commit("POP_UNDO");

      let arr = state.canvas._objects.filter(o => o.lxwname);

      //加载数据并重新渲染
      state.canvas.loadFromJSON(lastState, () => {
        state.canvas.add(...arr);
        dispatch("zhiding");

        state.canvas.renderAll();
      });
    },

    // 恢复
    redo({ commit, dispatch, state }) {
      //读取最近的一个信息
      commit("ADD_UNDO", state.canvasState);
      const lastState = { ...state.redoList[state.redoList.length - 1] };

      commit("SET_CANVASSTATE", lastState);

      commit("POP_REDO");

      let arr = state.canvas._objects.filter(o => o.lxwname);
      //加载数据并重新渲染
      state.canvas.loadFromJSON(lastState, () => {
        state.canvas.add(...arr);
        dispatch("zhiding");

        state.canvas.renderAll();
      });
    },
    // 预览图片
    setPreviewImg({ commit }, img) {
      commit("SET_PREVIEW_IMG", img);
    }
  }
};

export default app;
